using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace Times
{
    public partial class DesktopForm : Form
    {
        private List<PrayerTimes> calendar = new List<PrayerTimes>();
        private PrayerTimes today;
        private string message = "";
        private string shortMessage = "";
        private int WARNING = (int)Times.Properties.Settings.Default.WarnTime;
        private int CRITICAL = (int)Times.Properties.Settings.Default.AlertTime;

        private class PrayerTimes
        {
            public DateTime date;
            public DateTime fajr;
            public DateTime sunrise;
            public DateTime dhuhr;
            public DateTime asr;
            public DateTime maghrib;
            public DateTime isha;
        }

        private enum TimeSlot
        {
            Fajr,
            Sunrise,
            Dhuhr,
            Asr,
            Maghrib,
            Isha
        }
       
        public DesktopForm()
        {
            InitializeComponent();
            this.Opacity = (double)Properties.Settings.Default.Transparency / 100;
            LoadTimes();
            SetToday();
            CheckTime();
            SetLock(Properties.Settings.Default.LockOnDesktop);

			timer1.Start();
			timer2.Start();
            if (Properties.Settings.Default.StartMinimized)
            {
                Hide();
            }
            else
            {
                Show();
            }
        }

		private void LoadTimes()
		{
			calendar = new List<PrayerTimes>();
			SalaahTimeCalculator calc = new SalaahTimeCalculator();
			calc.setCalculationMethod(parseEnum<CalculationMethods>(Properties.Settings.Default.CalculationMethod, CalculationMethods.ISNA));
			calc.setAsrJurusticionType(parseEnum<JurusticMethods>(Properties.Settings.Default.Madhab, JurusticMethods.Hanafi));
			int timeZone = Properties.Settings.Default.TimeZone;
			if (Properties.Settings.Default.IsDST)
				timeZone = timeZone + 1;
			string[] userTimes = calc.getPrayerTimes(DateTime.Now, Properties.Settings.Default.Latitude, Properties.Settings.Default.Longitude, timeZone);
			PrayerTimes pt = new PrayerTimes();
			DateTime[] dtTimes = calc.getDateTimeRepresentation(userTimes);
			pt.fajr = dtTimes[0];
			pt.sunrise = dtTimes[1];
			pt.dhuhr = dtTimes[2];
			pt.asr = dtTimes[3];
			pt.maghrib = dtTimes[5];
			pt.isha = dtTimes[6];
			pt.date = DateTime.Now;
			calendar.Add(pt);
		}

		private static T parseEnum<T>(string value, T defaultValue)
		{
			if (string.IsNullOrEmpty(value))
				return defaultValue;

			T result = defaultValue;
			try
			{
				result = (T)Enum.Parse(defaultValue.GetType(), value);
			}
			catch { }

			return result;
		}

        private void LoadTimesFromCSV() {
            calendar = new List<PrayerTimes>();
            today = new PrayerTimes();
            message = "";

            string strFileName = Application.StartupPath + "\\Resources\\" + Properties.Settings.Default.DataFile;

            TextReader reader = null ;
            try
            {
                reader = new StreamReader(strFileName);
                string input = "";
                string line = "";
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splitLine = line.Split(',');
                    if (splitLine[0].Equals("Date"))
                        continue;

                    PrayerTimes pt = new PrayerTimes();
                    // Parse Date
                    try
                    {
                        pt.date = DateTime.Parse(splitLine[0]);
                        pt.date = new DateTime(System.DateTime.Now.Year,
                            pt.date.Month, pt.date.Day);
                    }
                    catch (FormatException e)
                    {}
                    catch (ArgumentOutOfRangeException e)
                    {}
                    // Parse Fajr
                    try
                    {
                        pt.fajr = DateTime.Parse(splitLine[1]);
                    }
                    catch (FormatException e)
                    {}
                    // Parse Sunrise
                    try
                    {
                        pt.sunrise = DateTime.Parse(splitLine[2]);
                    }
                    catch (FormatException e)
                    { }
                    // Parse Dhuhr
                    try
                    {
                        pt.dhuhr = DateTime.Parse(splitLine[3]);
                    }
                    catch (FormatException e)
                    { }
                    // Parse Asr
                    try
                    {
                        pt.asr = DateTime.Parse(splitLine[4]);
                    }
                    catch (FormatException e)
                    { }
                    // Parse Maghrib
                    try
                    {
                        pt.maghrib = DateTime.Parse(splitLine[5]);
                    }
                    catch (FormatException e)
                    { }
                    // Parse Isha
                    try
                    {
                        pt.isha = DateTime.Parse(splitLine[6]);
                    }
                    catch (FormatException e)
                    { }
                    calendar.Add(pt);
                }
            }
            catch (Exception e) {
                message = "Could not open the file.";
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            
        }

        private void SetToday()
        {
            foreach (PrayerTimes pt in calendar)
            {
                DateTime now = System.DateTime.Now;
                if (pt.date.Year == now.Year &&
                    pt.date.Month == now.Month &&
                    pt.date.Day == now.Day)
                {
                    today = pt;
                    break;
                }
            }
        }

        private void SetMessage()
        {
            if (Properties.Settings.Default.ShowAllTimes)
            {
                lblOutput.Text = message;
            } else {
                lblOutput.Text = shortMessage;
            }
            notifyIcon1.Text = shortMessage;
            this.Height = this.lblOutput.Height;
            this.Width = this.lblOutput.Width;
        }

        private void CheckTime()
        {
            int level = 0; // 0 - normal, 1 - warning, 2 - critical
            TimeSlot slot = new TimeSlot();
            TimeSpan diff = new TimeSpan();
            
            DateTime now = System.DateTime.Now;
            if (today != null)
            {
                if (now > today.isha)
                {
                    slot = TimeSlot.Isha;
                    // Do nothing
                }
                else if (now > today.maghrib)
                {
                    diff = today.isha.Subtract(now);
                    slot = TimeSlot.Maghrib;
                                        
                    if (now.AddMinutes(CRITICAL) > today.isha)
                    {
                        level = 2;
                    }
                    else if (now.AddMinutes(WARNING) > today.isha)
                    {
                        level = 1;
                    }
                }
                else if (now > today.asr)
                {
                    diff = today.maghrib.Subtract(now);
                    slot = TimeSlot.Asr;
                    
                    if (now.AddMinutes(CRITICAL) > today.maghrib)
                    {
                        level = 2;
                    }
                    else if (now.AddMinutes(WARNING) > today.maghrib)
                    {
                        level = 1;
                    }
                }
                else if (now > today.dhuhr)
                {
                    diff = today.asr.Subtract(now);
                    slot = TimeSlot.Dhuhr;
                    
                    if (now.AddMinutes(CRITICAL) > today.asr)
                    {
                        level = 2;
                    }
                    else if (now.AddMinutes(WARNING) > today.asr)
                    {
                        level = 1;
                    }
                }
                else if (now > today.sunrise)
                {
                    diff = today.dhuhr.Subtract(now);
                    slot = TimeSlot.Sunrise;
                    
                    if (now.AddMinutes(CRITICAL) > today.dhuhr)
                    {
                        level = 2;
                    }
                    else if (now.AddMinutes(WARNING) > today.dhuhr)
                    {
                        level = 1;
                    }
                }
                else if (now > today.fajr && now < today.sunrise)
                {
                    diff = today.sunrise.Subtract(now);
                    slot = TimeSlot.Fajr;
                   
                    if (now.AddMinutes(CRITICAL) > today.sunrise)
                    {
                        level = 2;
                    }
                    else if (now.AddMinutes(WARNING) > today.sunrise)
                    {
                        level = 1;
                    }
                }

                message = "Dhuhr: " + today.dhuhr.ToShortTimeString() + Environment.NewLine +
                        "Asr: " + today.asr.ToShortTimeString() + Environment.NewLine +
                        "Maghrib: " + today.maghrib.ToShortTimeString() + Environment.NewLine +
                        "Isha: " + today.isha.ToShortTimeString();
                switch (slot)
                {
                    case TimeSlot.Fajr : shortMessage = "Sunrise: " + today.sunrise.ToShortTimeString(); break;
                    case TimeSlot.Sunrise: shortMessage = "Dhuhr: " + today.dhuhr.ToShortTimeString(); break;
                    case TimeSlot.Dhuhr: shortMessage = "Asr: " + today.asr.ToShortTimeString(); break;
                    case TimeSlot.Asr: shortMessage = "Maghrib: " + today.maghrib.ToShortTimeString(); break;
                    case TimeSlot.Maghrib: shortMessage = "Isha: " + today.isha.ToShortTimeString(); break;
                    case TimeSlot.Isha: shortMessage = "Fajr: " + today.fajr.ToShortTimeString(); break;
                }

                message +=  Environment.NewLine + "Time Left: " + String.Format("{0:0}:{1:00}", diff.Hours, diff.Minutes);
                shortMessage += Environment.NewLine + "Time Left: " + String.Format("{0:0}:{1:00}", diff.Hours, diff.Minutes);

                if (level == 2)
                {
                    this.notifyIcon1.Icon = Times.Properties.Resources.clock_sm_orange;
                    this.ForeColor = Properties.Settings.Default.AlertColor;
                }
                else if (level == 1)
                {
                    this.notifyIcon1.Icon = Times.Properties.Resources.clock_sm_yellow;
                    this.ForeColor = Properties.Settings.Default.WarnColor;
                }
                else
                {
                    this.notifyIcon1.Icon = Times.Properties.Resources.clock_sm;
                    this.ForeColor = Properties.Settings.Default.NormColor;
                }
            }
            else
            {
                message = "No data found.";
            }
            SetMessage();
        }

        public void RefreshData()
        {
            WARNING = (int)Times.Properties.Settings.Default.WarnTime;
            CRITICAL = (int)Times.Properties.Settings.Default.AlertTime;
            this.Opacity = (double)Properties.Settings.Default.Transparency/100;
            LoadTimes();
            SetToday();
            CheckTime();
        }

        private void SetLock(bool Check)
        {
            if (!Check)
            {
                itemLock.Checked = false;
                this.lblOutput.MouseDown += frm_MouseDown;
                this.lblOutput.MouseMove += frm_MouseMove;
                this.lblOutput.MouseUp += frm_MouseUp;
                this.Cursor = Cursors.SizeAll;
                Properties.Settings.Default.LockOnDesktop = false;
            }
            else
            {
                itemLock.Checked = true;
                this.lblOutput.MouseDown -= frm_MouseDown;
                this.lblOutput.MouseMove -= frm_MouseMove;
                this.lblOutput.MouseUp -= frm_MouseUp;
                this.Cursor = Cursors.Default;
                Properties.Settings.Default.LockOnDesktop = true;
            }
        }

        #region Misc Events
        private Point mouseOffset;
        private bool isMouseDown = false;

        private void frm_MouseDown(object sender,
        System.Windows.Forms.MouseEventArgs e)
        {
            int xOffset;
            int yOffset;
            if (e.Button == MouseButtons.Left)
            {
                xOffset = -e.X;
                yOffset = -e.Y;

                mouseOffset = new Point(xOffset, yOffset);
                isMouseDown = true;
            }
        }
        private void frm_MouseMove(object sender,
        System.Windows.Forms.MouseEventArgs e)
        {
            if (isMouseDown)
            {
                Point mousePos = Control.MousePosition;
                mousePos.Offset(mouseOffset.X, mouseOffset.Y);
                Location = mousePos;
            }
        }

        private void frm_MouseUp(object sender,
        System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = false;
            }
        }
        
        private void itemClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void itemResize_Click(object sender, EventArgs e)
        {
            if (!Visible)
            {
                Show();
            }
            else
            {
                Hide();
            }
        }

        private void itemRefresh_Click(object sender, EventArgs e)
        {
            RefreshData();
        }
        
        private void timer_Ticks(object sender, EventArgs e)
        {
            CheckTime();
        }


		private void timer2_Tick(object sender, EventArgs e)
		{
			RefreshData();
		}

        private void frm_Closing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.Location = new Point(10, 10);
            
        }

        private void cmMenu_Opening(object sender, CancelEventArgs e)
        {
            if (!Visible)
            {
                itemResize.Text = "&Show on Desktop";
            }
            else
            {
                itemResize.Text = "&Hide from Desktop";
            }
        }

        private void itemOptions_Click(object sender, EventArgs e)
        {
            Options frm = new Options(this);
            frm.Show(this);
			LoadTimes();
        }

        private void itemLock_Click(object sender, EventArgs e)
        {
            if (itemLock.Checked)
            {
                SetLock(false);
            }
            else
            {
                SetLock(true);
            }
        }
        #endregion
    }
}